/**
 * 认证服务实现类 - 用户认证和企业注册的核心业务逻辑实现
 *
 * 开发人员：徐少洋
 * 开发时间：2025-10-20 至 2025-10-25
 * 模块职责：实现用户认证、企业注册、JWT令牌管理等核心认证业务逻辑
 *
 * 技术要点：
 * - 多租户用户认证和权限验证
 * - BCrypt密码加密和验证机制
 * - JWT令牌生成和管理策略
 * - 企业注册和管理员账户创建
 * - 事务管理和异常处理机制
 *
 * 开发故事：负责认证服务的核心业务逻辑实现，与认证控制器、安全配置、数据库层深度配合，确保系统认证的安全性和可靠性。
 */
package com.pbl.auth;

import com.pbl.common.exception.BizException;
import com.pbl.dto.EnterpriseRegisterRequest;
import com.pbl.entity.Enterprise;
import com.pbl.entity.Role;
import com.pbl.entity.User;
import com.pbl.entity.UserRole;
import com.pbl.entity.UserRoleId;
import com.pbl.repository.EnterpriseRepository;
import com.pbl.repository.RoleRepository;
import com.pbl.repository.UserRepository;
import com.pbl.repository.UserRoleRepository;
import com.pbl.security.JwtUtil;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.Map;

@Service
public class AuthServiceImpl implements AuthService {

    private final UserRepository userRepository;
    private final EnterpriseRepository enterpriseRepository;
    private final RoleRepository roleRepository;
    private final UserRoleRepository userRoleRepository;
    private final PasswordEncoder passwordEncoder;
    private final JwtUtil jwtUtil;

    /**
     * 构造认证服务实现
     * @param userRepository 用户数据访问层
     * @param enterpriseRepository 企业数据访问层
     * @param roleRepository 角色数据访问层
     * @param userRoleRepository 用户角色数据访问层
     * @param passwordEncoder 密码加密器
     */
    public AuthServiceImpl(UserRepository userRepository, EnterpriseRepository enterpriseRepository,
                          RoleRepository roleRepository, UserRoleRepository userRoleRepository,
                          PasswordEncoder passwordEncoder) {
        this.userRepository = userRepository;
        this.enterpriseRepository = enterpriseRepository;
        this.roleRepository = roleRepository;
        this.userRoleRepository = userRoleRepository;
        this.passwordEncoder = passwordEncoder;
        // 开发环境默认密钥，生产环境应通过配置注入
        this.jwtUtil = new JwtUtil("pbl-secret-key-please-change-please-change-123456", 24 * 3600_000L);
    }

    @Override
    public Map<String, Object> login(Long enterpriseId, String username, String password) {
        User user = userRepository.findByEnterprise_IdAndUsername(enterpriseId, username)
                .orElseThrow(() -> new BizException(401, "用户名或密码错误"));
        if (!passwordEncoder.matches(password, user.getPasswordHash())) {
            throw new BizException(401, "用户名或密码错误");
        }
        Map<String, Object> claims = new HashMap<>();
        claims.put("enterpriseId", enterpriseId);
        claims.put("userId", user.getId());
        String token = jwtUtil.generateToken(username, claims);
        
        // 返回登录信息
        Map<String, Object> result = new HashMap<>();
        result.put("token", token);
        result.put("enterpriseId", enterpriseId);
        result.put("enterpriseName", user.getEnterprise().getName());
        result.put("userId", user.getId());
        result.put("username", user.getUsername());
        return result;
    }

    @Override
    public User register(Long enterpriseId, String username, String password, String email) {
        Enterprise ent = enterpriseRepository.findById(enterpriseId).orElseThrow(() -> new BizException(404, "企业不存在"));
        userRepository.findByEnterprise_IdAndUsername(enterpriseId, username).ifPresent(u -> {
            throw new BizException(400, "用户名已存在");
        });
        User u = new User();
        u.setEnterprise(ent);
        u.setUsername(username);
        u.setPasswordHash(passwordEncoder.encode(password));
        u.setEmail(email);
        u.setStatus(1);
        return userRepository.save(u);
    }

    @Override
    @Transactional
    public Map<String, Object> registerEnterprise(EnterpriseRegisterRequest request) {
        // 1. 创建企业
        Enterprise enterprise = new Enterprise();
        enterprise.setName(request.getEnterpriseName());
        enterprise.setCreditCode(request.getCreditCode());
        enterprise.setContactName(request.getContactName());
        enterprise.setContactPhone(request.getContactPhone());
        enterprise.setStatus(1);
        enterprise = enterpriseRepository.save(enterprise);

        // 2. 创建管理员角色
        Role adminRole = Role.builder()
                .enterprise(enterprise)
                .code("ADMIN")
                .name("管理员")
                .description("系统管理员，拥有全部权限")
                .builtIn(1)
                .build();
        adminRole = roleRepository.save(adminRole);

        // 3. 创建管理员用户
        User admin = new User();
        admin.setEnterprise(enterprise);
        admin.setUsername(request.getUsername());
        admin.setEmail(request.getEmail());
        admin.setPasswordHash(passwordEncoder.encode(request.getPassword()));
        admin.setStatus(1);
        admin = userRepository.save(admin);

        // 4. 分配管理员角色
        UserRole userRole = new UserRole();
        UserRoleId userRoleId = new UserRoleId();
        userRoleId.setUserId(admin.getId());
        userRoleId.setRoleId(adminRole.getId());
        userRole.setId(userRoleId);
        userRole.setUser(admin);
        userRole.setRole(adminRole);
        userRoleRepository.save(userRole);

        // 5. 生成JWT token
        Map<String, Object> claims = new HashMap<>();
        claims.put("enterpriseId", enterprise.getId());
        claims.put("userId", admin.getId());
        String token = jwtUtil.generateToken(admin.getUsername(), claims);

        // 6. 返回结果
        Map<String, Object> result = new HashMap<>();
        result.put("token", token);
        result.put("enterpriseId", enterprise.getId());
        result.put("enterpriseName", enterprise.getName());
        result.put("userId", admin.getId());
        result.put("username", admin.getUsername());
        return result;
    }
}
